<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
<meta name="generator" content="Doxygen 1.9.4"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Arduino LibLAME: MP3 Encoding with LAME</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr id="projectrow">
  <td id="projectalign">
   <div id="projectname">Arduino LibLAME
   </div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.9.4 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
var searchBox = new SearchBox("searchBox", "search",'Search','.html');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
/* @license-end */
</script>
<div id="main-nav"></div>
</div><!-- top -->
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div><div class="header">
  <div class="headertitle"><div class="title">MP3 Encoding with LAME </div></div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p ><a class="anchor" id="md_README"></a> <a href="https://lame.sourceforge.io/about.php">LAME</a> is a open source implementation of a MP3 encoder. This project just reorganized the code to follow Arduino Library conventions, so that you can use it in Arduino and PlatformIO.</p>
<p >I have also added a simple Arduino style C++ API which allows to output the resulting MP3 via to a Arduino Stream or to receive it via a callback.</p>
<h2><a class="anchor" id="autotoc_md1"></a>
API</h2>
<p >Here is an example Arduino sketch for encoding PCM data into MP3:</p>
<div class="fragment"><div class="line">#include &quot;MP3EncoderLAME.h&quot;</div>
<div class="line">#include &lt;stdlib.h&gt;  // for rand</div>
<div class="line"> </div>
<div class="line">using namespace liblame;</div>
<div class="line"> </div>
<div class="line">void dataCallback(uint8_t *mp3_data, size_t len) {</div>
<div class="line">    Serial.print(&quot;mp3 generated with &quot;);</div>
<div class="line">    Serial.print(len);</div>
<div class="line">    Serial.println(&quot; bytes&quot;);</div>
<div class="line">}</div>
<div class="line"> </div>
<div class="line">MP3EncoderLAME mp3(dataCallback);</div>
<div class="line">AudioInfo info;</div>
<div class="line">int16_t buffer[512];</div>
<div class="line"> </div>
<div class="line">void setup() {</div>
<div class="line">    Serial.begin(115200);</div>
<div class="line"> </div>
<div class="line">    info.channels = 1;</div>
<div class="line">    info.sample_rate = 44100;</div>
<div class="line">    mp3.begin(info);</div>
<div class="line"> </div>
<div class="line">    Serial.println(&quot;writing...&quot;);</div>
<div class="line"> </div>
<div class="line">}</div>
<div class="line"> </div>
<div class="line">void loop() {</div>
<div class="line">    Serial.println(&quot;writing 512 samples of random data&quot;);</div>
<div class="line">    for (int j=0;j&lt;512;j++){</div>
<div class="line">        buffer[j] = (rand() % 100) - 50;         </div>
<div class="line">    }</div>
<div class="line">    mp3.write(buffer, 512*sizeof(int16_t));</div>
<div class="line">}</div>
</div><!-- fragment --><h2><a class="anchor" id="autotoc_md2"></a>
Installation</h2>
<p >In Arduino, you can download the library as zip and call include Library -&gt; zip library. Or you can git clone this project into the Arduino libraries folder e.g. with</p>
<div class="fragment"><div class="line">cd  ~/Documents/Arduino/libraries</div>
<div class="line">git clone pschatzmann/arduino-liblame.git</div>
</div><!-- fragment --><p >This project can also be built and executed on your desktop with cmake:</p>
<div class="fragment"><div class="line">cd arduino-liblame</div>
<div class="line">mkdir build</div>
<div class="line">cd build</div>
<div class="line">cmake ..</div>
<div class="line">make</div>
</div><!-- fragment --><h2><a class="anchor" id="autotoc_md3"></a>
Documentation</h2>
<ul>
<li>The <a href="https://pschatzmann.github.io/arduino-liblame/html/annotated.html">Class Documentation can be found here</a></li>
<li>You can also find some <a href="https://www.pschatzmann.ch/home/2021/08/10/an-mp3-encoder-for-arduino/">more information in my dedicated Blog</a>.</li>
<li>I also suggest that you have a look at <a href="https://www.pschatzmann.ch/home/2021/08/13/audio-decoders-for-microcontrollers/">my overview Blog</a></li>
</ul>
<p >I recommend to use this library together with my <a href="https://github.com/pschatzmann/arduino-audio-tools">Arduino Audio Tools</a>. This is just one of many <b>codecs</b> that I have collected so far: Further details can be found in the <a href="https://github.com/pschatzmann/arduino-audio-tools/wiki/Encoding-and-Decoding-of-Audio">Encoding and Decoding Wiki</a> of the Audio Tools.</p>
<h2><a class="anchor" id="autotoc_md4"></a>
Memory/RAM</h2>
<p >This library requires quite a lot of RAM and it should work if you just use this decoder w/o any additional functionality that requires additional RAM. If you want to use e.g. WIFI together with this library you might not have enough RAM: Fortunately this library supports PSRAM so if you activate PSRAM you should have more then enough headroom... <br  />
</p>
<h2><a class="anchor" id="autotoc_md5"></a>
Changes to the Original Code</h2>
<p >The initial restructured code was working prefectly with my <a href="https://github.com/pschatzmann/Arduino-Emulator">Arduino Simulator</a> on the desktop, but as soon I as I deployed it on an ESP32 it was crashing because of different reasons:</p>
<ul>
<li>The memory structures were partly too big</li>
<li>Long arrays were allocated on the stack</li>
</ul>
<p >So I needed to adjust the original code quite a bit. You can activate some micro processor specific functionaitly in config.h.</p>
<div class="fragment"><div class="line">// use dynamically precalculated log table</div>
<div class="line">#define USE_FAST_LOG 0</div>
<div class="line"> </div>
<div class="line">// use precalculated log table as const -&gt; in the ESP32 this will end up in flash memory</div>
<div class="line">#define USE_FAST_LOG_CONST 1</div>
<div class="line"> </div>
<div class="line">// Avoid big memory allocations in replaygain_data</div>
<div class="line">#define USE_MEMORY_HACK 1</div>
<div class="line"> </div>
<div class="line">// Not all microcontroller support vararg methods: alternative impelemtation of logging using the preprocessor</div>
<div class="line">#define USE_LOGGING_HACK 1</div>
<div class="line"> </div>
<div class="line">// Print debug and trace messages</div>
<div class="line">#define USE_DEBUG 0</div>
<div class="line"> </div>
<div class="line">// Print memory allocations and frees</div>
<div class="line">#define USE_DEBUG_ALLOC 0</div>
<div class="line"> </div>
<div class="line">// The stack on microcontrollers is very limited - use the heap for big arrays instead of the stack! </div>
<div class="line">#define USE_STACK_HACK 1</div>
</div><!-- fragment --> </div></div><!-- PageDoc -->
</div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated by&#160;<a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.4
</small></address>
</body>
</html>
